package com.yuke.cloud.service.omc.controller.frontend;

/*
 * <p>Company: Copyright (c) 2018. yuke All Rights Reserved. </br> </p>
 * <p>Title：yuke-mall </br> </p>
 * <p>com.yuke.cloud.service.omc.controller.frontend Description TODO </br> </p>
 * @Author wg
 * @Date   2020/6/9 17:12
 */

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yuke.cloud.common.base.constant.GlobalConstant;
import com.yuke.cloud.common.base.constant.MQConstants;
import com.yuke.cloud.common.core.mq.RabbitMetaMessage;
import com.yuke.cloud.common.core.mq.RabbitSender;
import com.yuke.cloud.common.util.PublicUtil;
import com.yuke.cloud.common.util.wrapper.WrapMapper;
import com.yuke.cloud.common.util.wrapper.Wrapper;
import com.yuke.cloud.service.api.cmc.dto.CmsSecKillSkuDto;
import com.yuke.cloud.service.api.cmc.service.CmcFeignApi;
import com.yuke.cloud.service.api.wmc.dto.StorageSpecInfoDto;
import com.yuke.cloud.service.api.wmc.dto.WmsGiftDto;
import com.yuke.cloud.service.api.wmc.service.WmcStorageFeignApi;
import com.yuke.cloud.service.omc.dto.OrderBasicDto;
import com.yuke.cloud.service.omc.dto.OrderGoodsDto;
import com.yuke.cloud.service.omc.dto.OrderInfoDto;
import com.yuke.cloud.service.omc.entity.OdsOrder;
import com.yuke.cloud.service.omc.service.OdsOrderService;
import io.swagger.annotations.ApiOperation;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/mall/ods/order")
@Slf4j
public class MallOrderController {

    @Resource
    private OdsOrderService odsOrderService;
    @Resource
    private PayController payController;
    @Resource
    private OdsBillController odsBillController;
    @Resource
    private WmcStorageFeignApi wmcStorageFeignApi;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitSender rabbitSender;
    @Resource
    private CmcFeignApi cmcFeignApi;
    @Resource
    private WxPayController wxPayController;


    /**
     * 备用的提交订单程序，简化了很多不必要的库存查询
     *
     * @param orderInfoDto
     * @return
     */
    @Synchronized
    @PostMapping
    @ApiOperation(httpMethod = "POST", value = "新增订单")
    public Wrapper addOrder(@RequestBody OrderInfoDto orderInfoDto) {
        System.out.println("提交订单参数："+orderInfoDto);
        // 先判断提交的数据是否为空
        if (orderInfoDto == null || orderInfoDto.getUserId() == null || orderInfoDto.getOrderBasicDtos() == null ||
                orderInfoDto.getOrderBasicDtos().size() <= 0 || orderInfoDto.getRecipientDto() == null) {
            return WrapMapper.error("订单数据无效");
        }
        //获取shopId
        Long shopId = orderInfoDto.getOrderBasicDtos().get(0).getShopId();
        //若shopId为空则返回无店铺信息
        if (shopId == null) {
            return WrapMapper.error("订单数据无效，没有店铺信息");
        }
        //阻止反复提交，短时间内重复提交
        Object uId = redisTemplate.opsForValue().get("SendOrderAndUserId:" +orderInfoDto.getUserId());
        if (uId == null){
            String id = "SendOrderAndUserId:" +orderInfoDto.getUserId();
            Map<String, String> map = new HashMap();
            map.put("userId", orderInfoDto.getUserId().toString());
            redisTemplate.opsForValue().set(id, map, 10, TimeUnit.SECONDS);
        }else{
            return WrapMapper.error("提交太频繁，不可重复提交！");
        }



        // 判断订单中的商品库存是否满足订单需求
        Map<Long, Integer> goodsNumMap = new HashMap<>();
        Boolean isUserOrder = true;  // 店铺和用户单不可能一起提交，因此此处在for循环内赋值


        //获取订单基本信息集合 循环
        for (OrderBasicDto orderBasicDto : orderInfoDto.getOrderBasicDtos()) {
            //若订单类型 为店铺向平台仓库下单
            if (orderBasicDto.getOrderType() == 2) {
                isUserOrder = false;
            }
            //获取SpecId集合
            List<Long> specIdList = orderBasicDto.getOrderGoodsDtos().stream().map(OrderGoodsDto::getSpecId).collect(Collectors.toList());
            //获取商品所属仓库Id
            Long warehouseId = orderBasicDto.getWarehouseId();

            //todo 判断商品是否被禁用
            Map<Long,Integer> goodsStockMap = new HashMap<>();
            List<StorageSpecInfoDto> storageSpecInfoDtoList = wmcStorageFeignApi.getAllStorageBySpecIds(specIdList, warehouseId);
            if (storageSpecInfoDtoList != null && storageSpecInfoDtoList.size() > 0){
                for (StorageSpecInfoDto item : storageSpecInfoDtoList){
                    if (item.getStockPrice().equals(0) && !isUserOrder){
                        return WrapMapper.error("订单商品"+item.getSpecName()+"，批发价格错误！");
                    }
                    if (item.getMarketPrice().equals(0) && isUserOrder){
                        return WrapMapper.error("订单商品"+item.getSpecName()+"，市场价格错误！");
                    }
                    if (item.getNumber() - item.getLockNumber() < 1 ){
                        return WrapMapper.error("订单商品"+item.getSpecName()+"，库存不足！");
                    }
                    if(!item.getIsEnable() && !orderBasicDto.getOrderType().toString().equals("7")){ //忽略线下手工单
                        return WrapMapper.error("订单商品"+item.getSpecName()+"，已经下架！");
                    }
                    goodsStockMap.put(item.getSpecId(),item.getNumber() - item.getLockNumber());
                }
            }else{
                return WrapMapper.error("微服务异常！未找到订单商品");
            }
            //todo end

            Integer totalMoney = 0;
            Integer realMoney = 0;
            //获取商品规格信息集合遍历
            for (OrderGoodsDto orderGoodsDto : orderBasicDto.getOrderGoodsDtos()) {
                Integer stockNumber = goodsStockMap.get(orderGoodsDto.getSpecId());
                if (stockNumber < orderGoodsDto.getGoodsNum()){
                    return WrapMapper.error("订单商品"+orderGoodsDto.getSpecName()+"，货源紧张！");
                }
                //则将商品id放入集合中，去除重复记录，重复记录商品数量相加
                //根据商品Id获取商品库存数量
                Integer num = goodsNumMap.get(orderGoodsDto.getSpecId());
                //若商品数量为空或小于零
                if (num == null || num < 0) {
                    //则商品数量为零
                    num = 0;
                }
                //将商品Id作为键   放入map集合
                goodsNumMap.put(orderGoodsDto.getSpecId(), orderGoodsDto.getGoodsNum() + num);

                //totalMoney += orderGoodsDto.getGoodsPrice() * orderGoodsDto.getGoodsNum();
                //realMoney += orderGoodsDto.getPayPrice() * orderGoodsDto.getGoodsNum();
            }//for

            //orderBasicDto.setProductPriceTotal(totalMoney);
            //运费处理
            //Integer lmsprice = odsOrderService.getLmsPrice(orderBasicDto,orderInfoDto.getRecipientDto());
            //赠品处理
            List<OrderGoodsDto> giftGoodsDtos = odsOrderService.getWmsGiftList(orderBasicDto.getOrderGoodsDtos(),shopId,orderBasicDto.getOrderType());
            if (giftGoodsDtos != null && giftGoodsDtos.size() > 0){
                orderBasicDto.getOrderGoodsDtos().addAll(giftGoodsDtos);
            }
        }//for



        // add by wg 20190605 判断秒杀商品，只对用户端
        List<CmsSecKillSkuDto> cmsSecKillSkuDtos = null;
        //个人端购买
        if (isUserOrder) {
            cmsSecKillSkuDtos = odsOrderService.getSecKillSkus();
        }

        Iterator it = goodsNumMap.keySet().iterator();
        while (it.hasNext()) {
            //获取商品specId 转为String
            String key = it.next().toString();
            Integer goodsNum = goodsNumMap.get(Long.valueOf(key));
            // add by wg 20190605 判断秒杀商品
            // todo 从redis中获取活动商品并判断用户是否已经超买,暂时不做购买限制
            if (isUserOrder) {
                for (CmsSecKillSkuDto cmsSecKillSkuDto : cmsSecKillSkuDtos) {
                    if (cmsSecKillSkuDto.getSpecId().toString().equals(key)) {
                        if ((cmsSecKillSkuDto.getStoreCount() - cmsSecKillSkuDto.getLockCount()) < goodsNum) {
                            return WrapMapper.error("秒杀商品库存不足或收货地附近可能没有店铺，请检查后重新提交订单");
                        }
                        cmsSecKillSkuDto.setSaledCount(cmsSecKillSkuDto.getSaledCount() + goodsNum);
                        cmsSecKillSkuDto.setStoreCount(cmsSecKillSkuDto.getStoreCount());
                        cmsSecKillSkuDto.setLockCount(cmsSecKillSkuDto.getLockCount() + goodsNum);
                    }
                }
            }
        }


        // 生成订单，返回订单ID集合及应支付的总金额

        // todo 保存订单
        Map<String, String> mapResult = odsOrderService.saveOrder(orderInfoDto, cmsSecKillSkuDtos, isUserOrder);

        // todo 如果此单使用了优惠券，标记使用状态
        changeCoupon(orderInfoDto,mapResult);

        // todo 订单提交后处理
        Byte payType = 2;

        if (orderInfoDto.getOrderBasicDtos() != null && orderInfoDto.getOrderBasicDtos().size() > 0) {
            payType = orderInfoDto.getOrderBasicDtos().get(0).getPayType();

        }

        if (payType.toString().equals("0") || payType.toString().equals("8") || payType.toString().equals("9")) {
            // 货到付款方式，线下手工单,免费送,add by wg 20190711 增加货到付款方式
            // todo 此时直接通知仓库准备发货
           sendShippingMessage(orderInfoDto);
        } else {  // 线上支付方式
            if (PublicUtil.isNotEmpty(mapResult.get("pay_order_ids")) && PublicUtil.isNotEmpty(mapResult.get("totalpay"))) {
                double totalPay = Double.parseDouble(mapResult.get("totalpay"));
                String orderIds = mapResult.get("pay_order_ids");
                Object result = null;
                log.info("准备进入支付系统，orderIds={}, totalPay={}", orderIds, totalPay);
                Map<String, Object> map = new HashMap<String, Object>();

                map.put("paytype", "normal");
                map.put("pay_order_ids", orderIds);

                if (payType.toString().equals("2")) {  // 支付宝
                    map.put("totalpay", totalPay / 100);

                    JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                    // todo 调用支付接口
                    log.info("调用支付宝接口传入参数" + jsonObject1);
                    Wrapper wrapper = payController.orderPay(jsonObject1);
                    result = wrapper.getResult();
                    log.info("调用支付宝接口返回参数" + result);
                } else if (payType.toString().equals("3")) {  // 微信支付
                    map.put("totalpay", Integer.valueOf(mapResult.get("totalpay")));

                    JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                    try {
                        log.info("调用微信接口传入参数" + jsonObject1);
                        Wrapper wrapper = wxPayController.add(jsonObject1);
                        result = wrapper.getResult();
                        log.info("调用微信接口返回参数" + result);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                        return WrapMapper.error("微信支付失败");
                    }
                } else if (payType.toString().equals("4")) {  // 账户余额支付
                    map.put("totalpay", Integer.valueOf(mapResult.get("totalpay")));
                    map.put("userId", orderInfoDto.getUserId());
                    JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                    try {
                        log.info("调用账户余额接口传入参数" + jsonObject1);
                        Wrapper wrapper = odsBillController.consumer(jsonObject1);
                        result = wrapper.getResult();
                        log.info("调用账户余额接口返回参数" + result);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                        return WrapMapper.error("账户支付失败");
                    }
                } else if (payType.toString().equals("5")) {//积分支付
                    try {
                        Wrapper wrapper = odsOrderService.reduceOrderPoint(orderInfoDto,orderIds);
                        result =WrapMapper.ok(wrapper.getResult());
                        log.info("调用积分支付接口返回参数" + result);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                        return WrapMapper.error("积分支付失败");
                    }

                } else if (payType.toString().equals("6")) {//积分混购积分加支付宝
                    JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                    log.info("调用支付接口传入参数" + jsonObject1);
                    Wrapper wrapper = payController.orderPay(jsonObject1);
                    map.put("totalpay", totalPay / 100);
                    if (wrapper.getCode() > 200){
                        return WrapMapper.error("订单数据无效，支付宝支付错误");
                    }
                    Wrapper wrap = odsOrderService.reduceOrderPoint(orderInfoDto,orderIds);
                    if (wrap.getCode() > 200){
                        return WrapMapper.error("订单数据无效，积分扣减错误");
                    }
                    result = wrapper.getResult();
                    log.info("调用积分混合购支付宝接口返回参数" + result);
                } else if (payType.toString().equals("7")) {//积分混合购积分加微信
                    map.put("totalpay", Integer.valueOf(mapResult.get("totalpay")));

                    JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                    try {
                        Wrapper wrapper = wxPayController.add(jsonObject1);
                        if (wrapper.getCode() > 200){
                            return WrapMapper.error("订单数据无效，微信支付错误");
                        }
                        Wrapper wra = odsOrderService.reduceOrderPoint(orderInfoDto,orderIds);
                        if (wra.getCode() > 200){
                            return WrapMapper.error("订单数据无效");
                        }
                        result = wrapper.getResult();
                        log.info("调用积分混合购微信接口返回参数" + result);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                        return WrapMapper.error("微信支付失败");
                    }



                }


                if (result != null) {
                    //首单优惠券
                    //根据商户id，到ods_pay_order表查找
                    Example example = new Example(OdsOrder.class);
                    Example.Criteria criteria = example.createCriteria();
                    criteria.andEqualTo("shopId", shopId);
                    criteria.andEqualTo("orderStatus", 1);
                    List<OdsOrder> odsOrders = odsOrderService.selectByExample(example);
                    System.out.println("是否执行优惠券2#发放" + odsOrders);
                    //有记录>1跳过
                    if (odsOrders.size() == 1) {
                        //执行优惠券发放
                        System.out.println("执行优惠券2#发放");
                        cmcFeignApi.addCouponReceive(shopId, GlobalConstant.CouponType.FIRST_COUPON, 1);
                    }

                } else {
                    return WrapMapper.error("支付失败");
                }

                return WrapMapper.ok(result);
            } else {
                return WrapMapper.error("生成订单失败");
            }
        }

        return WrapMapper.ok(mapResult);
    }


    void changeCoupon(OrderInfoDto orderInfoDto,Map<String,String> mapResult){
        //如果此单使用了优惠券，标记使用状态,由于有的版本没传Coupon_receive_id，必须从redis中取值
        Long crId = orderInfoDto.getCouponReceiveId();
        System.out.println("如果此单使用了优惠券，标记使用状态" + crId);
        if (crId == null || crId.equals(0)) {
            String id = "CouponReceiveIdAndUserId:" +orderInfoDto.getUserId();
            Map<String, String> map = new HashMap();
            map = (Map<String, String>)redisTemplate.opsForValue().get(id);
            if (map != null){
                crId = Long.valueOf(map.get("CouponReceiveId"));
                Integer totalMoney = Integer.valueOf(map.get("totalMoney"));
                Integer productPriceTotal = orderInfoDto.getOrderBasicDtos().stream().mapToInt(OrderBasicDto::getProductPriceTotal).sum();
                if (totalMoney.equals(productPriceTotal)){
                    redisTemplate.delete(id);
                    cmcFeignApi.updateCouponReceive(crId, Long.valueOf(mapResult.get("pay_order_ids").toString()));
                    id = "CouponReceiveIdAndOrderId:" + mapResult.get("pay_order_ids");
                    map.put("OrderId", mapResult.get("pay_order_ids"));
                    redisTemplate.opsForValue().set(id, map, 4 * 60 * 60, TimeUnit.SECONDS);
                }

            }
        }
        else {
            cmcFeignApi.updateCouponReceive(crId, Long.valueOf(mapResult.get("pay_order_ids").toString()));

            String id = "CouponReceiveIdAndOrderId:" + mapResult.get("pay_order_ids");
            Map<String, String> map = new HashMap();
            map.put("CouponReceiveId", crId.toString());
            map.put("OrderId", mapResult.get("pay_order_ids"));
            redisTemplate.opsForValue().set(id, map, 4 * 60 * 60, TimeUnit.SECONDS);
        }
    }

    private void sendShippingMessage(OrderInfoDto orderInfoDto){
        String shopIds = null;
        String warehouseIds = null;
        for (OrderBasicDto orderBasicDto : orderInfoDto.getOrderBasicDtos()) {
            if (orderBasicDto.getShippingType() == 2) {  // 同城快送
                Long shopIdTemp = orderBasicDto.getShopId();
                if (shopIdTemp != null) {
                    if (PublicUtil.isEmpty(shopIds)) {
                        shopIds = orderBasicDto.getShopId().toString();
                    } else {
                        shopIds += ",";
                        shopIds += orderBasicDto.getShopId().toString();
                    }
                }
            }

            Long warehouseId = orderBasicDto.getWarehouseId();
            if (warehouseId != null) {
                if (PublicUtil.isEmpty(warehouseIds)) {
                    warehouseIds = orderBasicDto.getWarehouseId().toString();
                } else {
                    warehouseIds += ",";
                    warehouseIds += orderBasicDto.getWarehouseId().toString();
                }
            }
        }


        Map map = new HashMap();
        map.put("MessageType", "findWarehouseAdmin");
        map.put("warehouseIds", warehouseIds);
        map.put("shopIds", shopIds);
        map.put("body", "你有新的订单需要发货");//"查找仓库管理员");
        RabbitMetaMessage rabbitMetaMessage = new RabbitMetaMessage();
        rabbitMetaMessage.setExchange(MQConstants.BUSINESS_EXCHANGE);
        rabbitMetaMessage.setRoutingKey(MQConstants.BUSINESS_KEY_WMC);
        rabbitMetaMessage.setPayload(JSON.toJSONString(map));
        try {
            rabbitSender.send(rabbitMetaMessage);
        } catch (Exception e) {
            log.error("rabbitSender.send()调用异常");
        }

    }


}
